package com.corewillsoft.fireflies.gameobjects.obstacles.trajectories;

import com.corewillsoft.fireflies.util.MathUtils;

import java.util.List;

/**
 * Class which implements calculations for circular trajectory of particular object
 */
public class CircularTrajectory extends Trajectory {
	private static final int TRAJECTORY_PARAMETERS_COUNT = 3;

	/**
	 * Radius of circular trajectory
	 */
	private float radius = 0f;

	/**
	 * X-coordinate of the center of circle of trajectory
	 */
	private float centerX = 0f;

	/**
	 * Y-coordinate of the center of circle of trajectory
	 */
	private float centerY = 0f;

	/**
	 * Constructor of class
	 * @param parameters - list of float parameters, must contain 3 elements:
	 * <ul>
	 * <li>0 - X-coordinate of the center of circle of trajectory</li>
	 * <li>1 - Y-coordinate of the center of circle of trajectory</li>
	 * <li>2 - radius of circular trajectory</li>
	 * </ul>
	 */
	public CircularTrajectory(List<Float> parameters) {
		super(parameters);

		int parametersCount = parameters.size();
		if (parametersCount != TRAJECTORY_PARAMETERS_COUNT) {
			//throw new RuntimeException("Wrong parameters count provided to CircularTrajectory: expected " + TRAJECTORY_PARAMETERS_COUNT + ", but provided " + parametersCount);
			return;
		}

		centerX = parameters.get(0);
		centerY = parameters.get(1);
		radius = parameters.get(2);
	}

	/**
	 * Calculates X- and Y- components of speed of object bound to this trajectory;
	 * object moves along circular trajectory determined by parameters passed to constructor of class,
	 * movement is always counter-clockwise;
	 * to get calculated speed components, one should call {@link com.corewillsoft.fireflies.gameobjects.obstacles.trajectories.Trajectory#getSpeedX()} and {@link com.corewillsoft.fireflies.gameobjects.obstacles.trajectories.Trajectory#getSpeedY()}
	 * after calling of this method
	 * @param x - current X-coordinate of the moving object
	 * @param y - current Y-coordinate of the object
	 * @param maxSpeed - maximal absolute value of speed of the moving object
	 */
	@Override
	public void calculateSpeed(float x, float y, float maxSpeed) {
		//determine x- and y- coordinates of the object in (xc, yc) coordinate system with the center in the center of circle of trajectory
		double xc = x - centerX;
		double yc = y - centerY;

		//phiOld is angle of coordinate vector of the object in (xc, yc) coordinate system
		double phiOld = MathUtils.getLineAngle(0, 0, xc, yc);

		/*
		deltaPhi is angle of rotation of coordinate vector as a result of next move of the object;
		this formula is derived from cosine law, considered triangle consists of old coordinate vector (before object's move)
		having length equal radius of the circle, new coordinate vector (after object's move) having the same length,
		and movement vector having length equal to maxSpeed
		 */
		double deltaPhi = Math.acos(1 - maxSpeed * maxSpeed / (2 * radius * radius));

		//phiNew is angle of coordinate vector after its movement
		double phiNew = phiOld - deltaPhi;

		/*
		calculate components of coordinate vector in (ksi; nu) orthogonal coordinate system, which has center in the center of
		circle of trajectory (as (xc; yc) system), ksi-axis is drawn along new coordinate vector, nu-axis is orthogonal to ksi-axis;
		therefore, angle between ksi-axis and xc-axis is phiNew
		 */
		double ksi = radius;
		double nu = 0;

		//calculate coordinates of new coordinate vector in (xc; yc) system by known coordinates in (ksi; nu) system
		double xcNew = MathUtils.getXByKsiNu(ksi, nu, phiNew);
		double ycNew = MathUtils.getYByKsiNu(ksi, nu, phiNew);

		//calculate coordinates of object in the (x; y) system
		double xNew = xcNew + centerX;
		double yNew = ycNew + centerY;

		//calculate components of current speed of the object as difference between its new and old positions
		speedX = (float) (xNew - x);
		speedY = (float) (yNew - y);
	}
}
